package com.ruoyi.teaching.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.teaching.domain.*;
import com.ruoyi.teaching.domain.vo.AttendanceArray;
import com.ruoyi.teaching.domain.vo.AttendanceBo;
import com.ruoyi.teaching.domain.vo.AttendanceMonthBo;
import com.ruoyi.teaching.domain.vo.AttendanceTime;
import com.ruoyi.teaching.mapper.*;
import com.ruoyi.teaching.service.IAttendanceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 考勤Service业务层处理
 *
 * @author wwh
 * @date 2024-02-19
 */
@Service
public class AttendanceServiceImpl implements IAttendanceService
{
    @Autowired
    private AttendanceMapper attendanceMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private TeachingPlanMapper teachingPlanMapper;

    @Autowired
    private ClassesMapper classesMapper;

    @Autowired
    private HolidayMapper holidayMapper;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 查询考勤
     *
     * @param id 考勤主键
     * @return 考勤
     */
    @Override
    public Attendance selectAttendanceById(Long id)
    {
        return attendanceMapper.selectAttendanceById(id);
    }

    /**
     * 查询考勤列表
     *
     * @param attendance 考勤
     * @return 考勤
     */
    @Override
    public List<AttendanceBo> selectAttendanceList(AttendanceBo attendance)
    {
        String date = attendance.getDate();
        String firstDay = date.substring(0,8) + "01";
        String year = date.substring(0, 4);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR,1);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format1 = simpleDateFormat.format(calendar.getTime());
        String nextYear = format1.substring(0, 4);
        List<Holiday> holidayList = holidayMapper.selectList(new LambdaQueryWrapper<Holiday>()
                .ge(Holiday::getDate, year)
                .le(Holiday::getDate, nextYear));
        List<String> collect = holidayList.stream().map(Holiday::getDate).collect(Collectors.toList());
            Integer count = teachingPlanMapper.selectCount(new LambdaQueryWrapper<TeachingPlan>()
                    .ge(TeachingPlan::getDate, firstDay)
                    .le(TeachingPlan::getDate, date)
                    .ne(TeachingPlan::getCourseContent,"休息")
                    .ne(TeachingPlan::getCourseContent,"特殊休息日")
                    .notIn(TeachingPlan::getDate, collect));
            attendance.setMonth(Integer.valueOf(date.substring(5,7)));
            List<Attendance> attendanceList = attendanceMapper.selectAttendanceList(attendance);
            List<AttendanceBo> attendanceBoList = new ArrayList<>();
            Integer timeSlot = attendance.getTimeSlot();
            attendanceList.stream().forEach(e ->{
                String[] split = e.getAttendance().substring(1, e.getAttendance().length() - 1).split(",");
                if( timeSlot == null ){
                    e.setAttendance((split[count-1].substring(1,6).split("-"))[0]);
                }else {
                    e.setAttendance((split[count-1].substring(1,6).split("-"))[timeSlot-1]);
                }
                AttendanceBo attendanceBo = new AttendanceBo();
                BeanUtils.copyBeanProp(attendanceBo,e);
                attendanceBoList.add(attendanceBo);
            });
            attendanceBoList.forEach( e -> {
                if( timeSlot == null ){
                    e.setTimeSlot(1);
                }else {
                    e.setTimeSlot(timeSlot);
                }
                e.setDate(date);
            });
            return attendanceBoList;
    }

    /**
     * 新增考勤
     *
     * @param attendance 考勤
     * @return 结果
     */
    @Override
    public int insertAttendance(Attendance attendance) throws ParseException {
        Date nowDate = DateUtils.getNowDate();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(nowDate);
        List<TeachingPlan> teachingPlanList = teachingPlanMapper.selectList(new LambdaQueryWrapper<TeachingPlan>().eq(TeachingPlan::getDate, format));
        List<Attendance> attendenceList = new ArrayList<>();
        List<String> list = new ArrayList<>();
        String attendanceString = "{|-|-|}";
        String year = format.substring(0, 4);
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH,1);
        String firstDay = simpleDateFormat.format(calendar.getTime());
        calendar.add(Calendar.MONTH,1);
        calendar.add(Calendar.DATE,-1);
        String lastDay = simpleDateFormat.format(calendar.getTime());
        calendar.add(Calendar.YEAR,1);
        String format1 = simpleDateFormat.format(calendar.getTime());
        String nextYear = format1.substring(0, 4);
        List<Holiday> holidayList = holidayMapper.selectList(new LambdaQueryWrapper<Holiday>()
                .ge(Holiday::getDate, year)
                .le(Holiday::getDate, nextYear));
        List<String> collect = holidayList.stream().map(Holiday::getDate).collect(Collectors.toList());
        teachingPlanList.stream().forEach( e -> {
            int month = nowDate.getMonth()+1;
            Long stage = (long)e.getStage();
            Long classesId = e.getClassesId();

            Integer count = teachingPlanMapper.selectCount(new LambdaQueryWrapper<TeachingPlan>()
                    .eq(TeachingPlan::getStage, stage)
                    .eq(TeachingPlan::getClassesId, classesId)
                    .ne(TeachingPlan::getCourseContent,"休息")
                    .notIn(TeachingPlan::getDate, collect)
                    .ne(TeachingPlan::getCourseContent,"特殊休息日")
                    .ge(TeachingPlan::getDate,firstDay)
                    .le(TeachingPlan::getDate,lastDay));
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("{");
            for (int i = 0; i < count; i++) {
                if( i == count - 1 ){
                    stringBuilder.append(attendanceString + "}");
                }else {
                    stringBuilder.append(attendanceString + ",");
                }
            }
            List<Student> studentList = studentMapper.selectList(new LambdaQueryWrapper<Student>().eq(Student::getClassesId, classesId));
            studentList.stream().forEach( s -> {
                Attendance builder = Attendance.builder()
                        .month(month)
                        .stage(stage)
                        .classesId(classesId)
                        .name(s.getName())
                        .build();
                attendenceList.add(builder);
                list.add(stringBuilder.toString());
            });
        });

        String sql = "INSERT INTO `ry-cloud`.`ya_attendance` ( `name`, `stage`, `classes_id`, `month` , `attendance`)" + "VALUES ( ?, ?, ?, ?, ? )";
        jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                Attendance attendences = attendenceList.get(i);
                String s = list.get(i);
                ps.setString(1,attendences.getName());
                ps.setLong(2,attendences.getStage());
                ps.setLong(3,attendences.getClassesId());
                ps.setInt(4,attendences.getMonth());
                ps.setString(5,s);
            }

            @Override
            public int getBatchSize() {
                return attendenceList.size();
            }
        });
        return 1;
    }

    /**
     * 修改考勤
     *
     * @param attendanceBoList 考勤
     * @return 结果
     */
    @Override
    public int updateAttendance(List<AttendanceBo> attendanceBoList) throws ParseException {
        if(CollectionUtils.isEmpty(attendanceBoList)){
            return 0;
        }
        String date = attendanceBoList.get(0).getDate();
        String firstDay = date.substring(0,8) + "01";
        String year = date.substring(0, 4);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR,1);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(calendar.getTime());
        String nextYear = format.substring(0, 4);
        List<Holiday> holidayList = holidayMapper.selectList(new LambdaQueryWrapper<Holiday>()
                .ge(Holiday::getDate, year)
                .le(Holiday::getDate, nextYear));
        List<String> collect = holidayList.stream().map(Holiday::getDate).collect(Collectors.toList());
        Integer count = teachingPlanMapper.selectCount(new LambdaQueryWrapper<TeachingPlan>()
                .ge(TeachingPlan::getDate, firstDay)
                .le(TeachingPlan::getDate, date)
                .ne(TeachingPlan::getCourseContent,"休息")
                .notIn(TeachingPlan::getDate, collect)
                .ne(TeachingPlan::getCourseContent,"特殊休息日"));
        List<Long> idList = attendanceBoList.stream().map(AttendanceBo::getId).collect(Collectors.toList());
        List<Attendance> attendanceList = attendanceMapper.selectList(new LambdaQueryWrapper<Attendance>()
                .in(Attendance::getId, idList));
        Integer timeSlot = attendanceBoList.get(0).getTimeSlot();
        attendanceList.stream().forEach( e ->{
        });
        for (int i = 0; i < attendanceList.size(); i++) {
            Attendance e = attendanceList.get(i);
            String[] split = e.getAttendance().substring(1, e.getAttendance().length() - 1).split(",");
            String[] childSplit = split[count - 1].substring(1, 6).split("-");
            childSplit[timeSlot-1] = attendanceBoList.get(i).getAttendance();
            split[count - 1] = "{" + childSplit[0] + "-" + childSplit[1] + "-" +  childSplit[2] + "}";
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("{");
            for (int j = 0; j < split.length; j++) {
                if (j == split.length - 1) {
                    stringBuilder.append(split[j] + "}");
                } else {
                    stringBuilder.append(split[j] + ",");
                }
            }
            e.setRemark(attendanceBoList.get(i).getRemark());
            e.setAttendance(stringBuilder.toString());
        }
        attendanceList.forEach( e -> attendanceMapper.update(null,new LambdaUpdateWrapper<Attendance>()
                .eq(Attendance::getId,e.getId())
                .set(Attendance::getAttendance,e.getAttendance())
                .set(Attendance::getRemark,e.getRemark())));
        return 1;
    }

    /**
     * 批量删除考勤
     *
     * @param ids 需要删除的考勤主键
     * @return 结果
     */
    @Override
    public int deleteAttendanceByIds(Long[] ids)
    {
        return attendanceMapper.deleteAttendanceByIds(ids);
    }

    /**
     * 删除考勤信息
     *
     * @param id 考勤主键
     * @return 结果
     */
    @Override
    public int deleteAttendanceById(Long id)
    {
        return attendanceMapper.deleteAttendanceById(id);
    }

    /**
     * 选择出席全部列表
     *
     * @param attendance 出席
     * @return {@link AttendanceMonthBo}
     */
    @Override
    public AttendanceMonthBo selectAttendanceAllList(AttendanceBo attendance) {
            Integer month = attendance.getMonth();
            Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        calendar.add(Calendar.YEAR,1);
        int nextYear = calendar.get(Calendar.YEAR);
        calendar.add(Calendar.YEAR,-1);
        Long stage = attendance.getStage();
            Long classesId = attendance.getClassesId();
            if(classesId == null){
                classesId = 2L;
            }
            AttendanceMonthBo attendanceMonthBo = new AttendanceMonthBo();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            if(month == null){
                calendar.add(Calendar.MONTH,-1);
                month = calendar.get(Calendar.MONTH)+1;
            }else {
                calendar.set(Calendar.MONTH,month-1);
            }
            calendar.set(Calendar.DAY_OF_MONTH,1);
            String firstDayOfMonth = simpleDateFormat.format(calendar.getTime());
            calendar.add(Calendar.MONTH,1);
            calendar.add(Calendar.DATE,-1);
            String lastDayOfMonth = simpleDateFormat.format(calendar.getTime());
            Classes classes = classesMapper.selectOne(new LambdaQueryWrapper<Classes>().eq(Classes::getId, classesId));
            if( classes == null){
                throw new ServiceException("班级不存在");
            }
            List<Holiday> holidayList = holidayMapper.selectList(new LambdaQueryWrapper<Holiday>()
                    .ge(Holiday::getDate, year)
                    .le(Holiday::getDate, nextYear));
            List<String> collect = holidayList.stream().map(Holiday::getDate).collect(Collectors.toList());
            List<TeachingPlan> teachingPlanList = teachingPlanMapper.selectList(new LambdaQueryWrapper<TeachingPlan>()
                    .ge(TeachingPlan::getDate, firstDayOfMonth)
                    .le(TeachingPlan::getDate, lastDayOfMonth)
                    .eq(TeachingPlan::getStage, stage)
                    .eq(TeachingPlan::getClassesId, classesId)
                    .ne(TeachingPlan::getCourseContent,"休息")
                    .ne(TeachingPlan::getCourseContent,"特殊休息日"));
            List<Attendance> attendanceList = attendanceMapper.selectList(new LambdaQueryWrapper<Attendance>()
                    .eq(Attendance::getStage, stage)
                    .eq(Attendance::getClassesId, classesId)
                    .eq(Attendance::getMonth, month));

            List<Student> studentList = studentMapper.selectList(new LambdaQueryWrapper<Student>().eq(Student::getClassesId, classesId));
            attendanceMonthBo.setMonth(firstDayOfMonth.substring(0,7));
            int days = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            attendanceMonthBo.setDays(days);
            String[] weekdaysString = new String[]{"天","一","二","三","四","五","六"};
            String[] weekdays = new String[days];
            String[] teachingPlans = new String[days];
            ArrayList<Integer> dateList = new ArrayList<>();
            teachingPlanList.forEach(e ->{
                dateList.add(Integer.valueOf(e.getDate().substring(8,10)));
            });
            calendar.set(Calendar.DAY_OF_MONTH,1);
            int n = 0;
            Integer selfStudyDay = classes.getSelfStudyDay();
            for (int i = 0; i < days; i++) {
                Integer weekday = calendar.get(Calendar.DAY_OF_WEEK);
                calendar.add(Calendar.DAY_OF_MONTH,1);
                weekdays[i] = weekdaysString[weekday-1];
                if( dateList.contains(i+1)){
                    if(teachingPlanList.get(n).getDay() != null){
                        teachingPlans[i] = "上课";
                        n++;
                    }else if ("特殊上课日".equals(teachingPlanList.get(n).getCourseContent())){
                        teachingPlans[i] = "上课";
                        n++;
                    }else if ("特殊自习日".equals(teachingPlanList.get(n).getCourseContent()) || "自习".equals(teachingPlanList.get(n).getCourseContent())){
                        teachingPlans[i] = "自习";
                        n++;
                    }else {
                        teachingPlans[i] = "休息";
                        n++;
                    }
                }else {
                    if(weekday == 1){
                        teachingPlans[i] = "休息";
                    }else if( weekday.equals(selfStudyDay+1) ){
                        teachingPlans[i] = "自习";
                    }else {
                        teachingPlans[i] = "上课";
                    }
                }
            }
            AttendanceArray[] attendanceArrays = new AttendanceArray[studentList.size()];
            ArrayList<Integer> sundayList = new ArrayList<>();
            calendar.set(Calendar.DAY_OF_MONTH,1);
            for (int i = 0; i < days - 1; i++) {
                int day = calendar.get(Calendar.DAY_OF_WEEK);
                calendar.add(Calendar.DAY_OF_MONTH,1);
                if(day == Calendar.SUNDAY){
                    sundayList.add(calendar.get(Calendar.DAY_OF_MONTH));
                }
            }
            if( CollectionUtils.isEmpty(attendanceList)){
//                String[] morningStatus = new String[days];
//                String[] noonStatus = new String[days];
//                String[] nightStatus = new String[days];
//                for (int j = 0; j < days; j++) {
//                    morningStatus[j] = "-";
//                    noonStatus[j] = "-";
//                    nightStatus[j] = "-";
//                }
//                for (int i = 0; i < studentList.size(); i++) {
//                    AttendanceTime[] attendanceTimes = new AttendanceTime[3];
//                    AttendanceArray attendanceArray = new AttendanceArray();
//                    AttendanceTime attendanceMorning = new AttendanceTime();
//                    AttendanceTime attendanceNoon = new AttendanceTime();
//                    AttendanceTime attendanceNight = new AttendanceTime();
//                    attendanceMorning.setTime("早");
//                    attendanceMorning.setStatus(morningStatus);
//                    attendanceNoon.setTime("中");
//                    attendanceNoon.setStatus(noonStatus);
//                    attendanceNight.setTime("晚");
//                    attendanceNight.setStatus(nightStatus);
//                    attendanceTimes[0] = attendanceMorning;
//                    attendanceTimes[1] = attendanceNoon;
//                    attendanceTimes[2] = attendanceNight;
//                    attendanceArray.setAttendance(attendanceTimes);
//                    attendanceArray.setName(studentList.get(i).getName());
//                    attendanceArrays[i] = attendanceArray;
//                }
                attendanceMonthBo.setWeekdays(weekdays);
                attendanceMonthBo.setTeachingPlans(teachingPlans);
//                attendanceMonthBo.setList(attendanceArrays);
                return attendanceMonthBo;
            }
            String[] status = new String[]{"-","√","旷课","迟到","请假"};
            for (int i = 0; i < attendanceList.size(); i++) {
                int m = 0;
                n = 0;
                String[] morningStatus = new String[days];
                String[] noonStatus = new String[days];
                String[] nightStatus = new String[days];
                AttendanceArray attendanceArray = new AttendanceArray();
                attendanceArray.setName(attendanceList.get(i).getName());
                AttendanceTime[] attendanceTimes = new AttendanceTime[3];
                String studentAttendance = attendanceList.get(i).getAttendance();
                String[] split = studentAttendance.substring(1, studentAttendance.length()).split(",");
                Calendar instance = Calendar.getInstance();
                for (int j = 0; j < days; j++) {
                    instance.set(Calendar.DAY_OF_MONTH,j+1);
                    if( dateList.contains(j+1)  && !collect.contains(simpleDateFormat.format(instance.getTime()))){
                        String[] childSpilt = split[m++].substring(1, 6).split("-");
                        if("|".equals(childSpilt[0])){
                            morningStatus[j] = "-";
                        }else {
                            morningStatus[j] = status[Integer.valueOf(childSpilt[0])];
                        }
                        if("|".equals(childSpilt[1])){
                            noonStatus[j] = "-";
                        }else {
                            noonStatus[j] = status[Integer.valueOf(childSpilt[1])];
                        }
                        if("|".equals(childSpilt[2])){
                            nightStatus[j] = "-";
                        }else {
                            nightStatus[j] = status[Integer.valueOf(childSpilt[2])];
                        }
                    }else if(sundayList.contains(j+1)){
                        morningStatus[j] = "-";
                        noonStatus[j] = "-";
                        nightStatus[j] = "-";
                    }else{
                            morningStatus[j] = "-";
                            noonStatus[j] = "-";
                            nightStatus[j] = "-";
                    }
                }
                AttendanceTime attendanceMorning = new AttendanceTime();
                AttendanceTime attendanceNoon = new AttendanceTime();
                AttendanceTime attendanceNight = new AttendanceTime();
                attendanceMorning.setTime("早");
                attendanceMorning.setStatus(morningStatus);
                attendanceNoon.setTime("中");
                attendanceNoon.setStatus(noonStatus);
                attendanceNight.setTime("晚");
                attendanceNight.setStatus(nightStatus);
                attendanceTimes[0] = attendanceMorning;
                attendanceTimes[1] = attendanceNoon;
                attendanceTimes[2] = attendanceNight;
                attendanceArray.setAttendance(attendanceTimes);
                attendanceArrays[i] = attendanceArray;
            }
            attendanceMonthBo.setWeekdays(weekdays);
            attendanceMonthBo.setTeachingPlans(teachingPlans);
            attendanceMonthBo.setList(attendanceArrays);
            return attendanceMonthBo;
    }
}
